package com.gcu.common.uikit.bubble

import android.content.Context
import android.graphics.*
import android.text.TextPaint
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
import com.gcu.common.R
import com.gcu.common.utils.ViewUtil

/**
 * 自定义气泡控件
 * @property mTextPaint TextPaint
 * @property mTextRect Rect
 * @property mTextContent String
 * @property mBackgroundPaint Paint
 * @property mBackgroundRect RectF
 * @property mTrianglePaint Paint
 * @property mTrianglePath Path
 * @property mTriangleOffset Float
 * @constructor
 */
class BubbleView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleArr: Int = 0
) : View(context, attrs, defStyleArr) {

    companion object {
        private val DEFAULT_RADIUS = ViewUtil.dp2px(4f)

        //padding
        private val PADDING_TOP = ViewUtil.dp2px(6f)
        private val PADDING_BOTTOM = ViewUtil.dp2px(6f)
        private val PADDING_LEFT = ViewUtil.dp2px(12f)
        private val PADDING_RIGHT = ViewUtil.dp2px(12f)

        private val DEFAULT_TEXT_SIZE = ViewUtil.dp2px(12f)

        //尖角
        private val TRIANGLE_WIDTH = ViewUtil.dp2px(10f)
        private val TRIANGLE_HEIGHT = ViewUtil.dp2px(5f)

        private const val GAP = 3
    }

    /**
     * 气泡内容
     * M text paint
     */
    private val mTextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
    private val mTextRect = Rect()
    private var mTextContent = "Bubble View"

    /**
     * 气泡背景
     * M background paint
     */
    private val mBackgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val mBackgroundRect = RectF()

    /**
     * 气泡尖角
     * M triangle paint
     */
    private val mTrianglePaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val mTrianglePath = Path()
    private var mTriangleOffset = 0f

    init {
        mTextPaint.color = Color.WHITE
        mTextPaint.textSize = DEFAULT_TEXT_SIZE
        mBackgroundPaint.color = ContextCompat.getColor(context, R.color.bubble_bg_color)
        mBackgroundPaint.style = Paint.Style.FILL
        mTrianglePaint.color = ContextCompat.getColor(context, R.color.bubble_bg_color)
        mTrianglePaint.style = Paint.Style.FILL

        updateBubbleViewSize()
    }

    /**
     * 调节气泡大小
     * @return Unit
     */
    private fun updateBubbleViewSize() {
        mTextPaint.getTextBounds(mTextContent, 0, mTextContent.length, mTextRect)
        mBackgroundRect.left = 0f
        mBackgroundRect.top = 0f
        mBackgroundRect.right = mTextRect.width() + PADDING_LEFT + PADDING_RIGHT
        mBackgroundRect.bottom = mTextRect.height() + PADDING_TOP + PADDING_BOTTOM
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var width = mBackgroundRect.width().toInt()
        var height = (mBackgroundRect.height() + TRIANGLE_HEIGHT).toInt()
        setMeasuredDimension(width, height)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        drawBackground(canvas)
        drawBubbleContent(canvas)
        drawTriangle(canvas)
    }

    /**
     * 气泡圆角背景
     * @param canvas Canvas
     * @return Unit
     */
    private fun drawBackground(canvas: Canvas) {
        canvas.drawRoundRect(mBackgroundRect, DEFAULT_RADIUS, DEFAULT_RADIUS, mBackgroundPaint)
    }

    /**
     * 气泡内容
     * 1. drawText不能实现换行问题，需要使用StaticLayout代替
     * 2. 居中问题，考虑基线对齐
     * @param canvas Canvas
     * @return Unit
     */
    private fun drawBubbleContent(canvas: Canvas) {
        val fontMetrics = mTextPaint.fontMetrics
        val baseLine = (mBackgroundRect.bottom + mBackgroundRect.top - fontMetrics.bottom - fontMetrics.top) / 2
        canvas.drawText(mTextContent, PADDING_LEFT, baseLine, mTextPaint)
    }

    /**
     * 绘制气泡尖角
     * @param canvas Canvas
     * @return Unit
     */
    private fun drawTriangle(canvas: Canvas) {
        mTrianglePath.moveTo(
            mBackgroundRect.centerX(),
            mBackgroundRect.height() - GAP
        )
        mTrianglePath.lineTo(
            mBackgroundRect.centerX() - TRIANGLE_WIDTH / 2,
            mBackgroundRect.height() - GAP
        )
        mTrianglePath.lineTo(
            mBackgroundRect.centerX(),
            mBackgroundRect.height() + TRIANGLE_HEIGHT
        )
        mTrianglePath.lineTo(
            mBackgroundRect.centerX() + TRIANGLE_WIDTH / 2,
            mBackgroundRect.height() - GAP
        )
        canvas.drawPath(mTrianglePath, mTrianglePaint)
    }
}